'use strict'
import axios from 'axios'
import Event from 'common/plug/Eventbus'
import Url from 'common/libs/Url'

/**
 * HTTP请求类，支持Vue挂载，搭配Event监听进行操作
 * 
 * @author Mon
 * @version 1.0.1
 */
class Http {
    /**
     * 请求根路径
     *
     * @type {String}
     */
    baseURL = '';

    /**
     * 请求头
     */
    headers = {
        'Content-Type': 'application/json; charset=utf-8',
        'X-Requested-With': 'XMLHttpRequest'
    }

    /**
     * 构造方法
     */
    constructor(baseURL, headers) {
        if (typeof (baseURL) == 'string' && baseURL != '') {
            this.baseURL = baseURL
        }

        if (typeof (headers) == 'object' && headers) {
            this.headers = headers
        }
    }

    /**
     * 设置请求根路径
     *
     * @param {*} baseURL 
     */
    setBaseURL(baseURL) {
        this.baseURL = baseURL
        return this
    }

    /**
     * 设置请求头
     *
     * @param {*} key 
     * @param {*} value 
     */
    setHeaders(key, value) {
        this.headers[key] = value
        return this
    }

    /**
     * 挂载到Vue
     */
    install(Vue, options) {
        Vue.prototype.$http = this
    }

    /**
     * 创建实例
     */
    create() {
        let config = {
            baseURL: this.baseURL,
            timeout: 3000,
            headers: this.headers,
            // before请求
            transformRequest: (data) => {
                // 触发http-before事件
                Event.emit('http-before', 'http', data)
                return data;
            },
            // after请求
            transformResponse: (data) => {
                // 触发http-after事件
                Event.emit('http-after', 'http', data)
                return data;
            }
        }
        return axios.create(config)
    }

    /**
     * 拦截请求
     *
     * @param {*} instance 	axios实例
     * @param {*} automatic 自动处理响应结果
     */
    interceptors(instance, automatic) {
        let _conf = {}
        // 添加请求拦截器
        instance.interceptors.request.use((config) => {
            _conf = config
            let queryData = Url.buildUri(config.data)
            // 设置请求头
            if (config.headers && typeof (config.headers) == 'object') {
                for (let key in config.headers) {
                    if (typeof (config.headers[key]) == 'string') {
                        _conf.headers[key] = config.headers[key]
                    }
                }
            }
            // 判断post请求，修正请求
            if (config.method == 'post') {
                _conf.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'
                _conf.data = queryData
            }
            // GET请求，处理参数
            if (config.method == 'get' && config.data != '' && config.data != undefined) {
                _conf.url = _conf.url + (_conf.url.indexOf('?') == '-1' ? '?' + queryData : queryData)
            }

            return _conf
        }, (error) => {
            // 触发http-query-faild事件
            Event.emit('http-request-faild', 'http', error)
            // 请求错误
            return Promise.reject(error)
        })

        // 添加响应拦截器
        instance.interceptors.response.use((res) => {
            let { data } = res
            if (typeof data == 'string') {
                data = JSON.parse(data)
            }
            // 请求失败
            if (Boolean(automatic) && data.code !== 1) {
                // 触发http-response-faild事件
                Event.emit('http-query-faild', 'http', data)
                // 拦截请求，抛出错误
                return Promise.reject({
                    messgae: 'query response faild',
                    config: _conf,
                    name: 'response faild',
                    data: data
                })
            }
            // 请求成功返回数据
            return data
        }, (error) => {
            // 触发http-response-faild事件
            Event.emit('http-response-faild', 'http', error)
            // 错误响应
            return Promise.reject(error)
        })
    }

    /**
     * 请求实例
     *
     * @param {*} options 
     */
    query(options) {
        let instance = this.create()
        options = Object.assign({}, options)
        let automatic = typeof options.automatic == 'undefined' ? true : options.automatic
        this.interceptors(instance, automatic)
        return instance(options)
    }
}

export default new Http